package mclight.selectors;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import mclight.containers.Container;
import mclight.text.Label;
import mclight.Style;
import mclight.ValueComponent;

class Knob extends ValueComponent
{	
	public function new(
		?parent:DisplayObjectContainer, ?container:Container, xpos:Float = 0, ypos:Float = 0,
		label:String = "", defaultHandler:Dynamic = null
	)
	{
		_precision = 1;
		_value = 0;
		_labelText = label;
		super(parent, container, xpos, ypos);
		if(defaultHandler != null)
		{
			//addEventListener(Event.CHANGE, defaultHandler);
		}
	}
	
	override function init():Void
	{
		super.init();
		setSize(40, 40);
	}
	
	var _knob:Sprite;
	
	var _label:Label;
	
	var _valueLabel:Label;
	
	override function construct():Void
	{
		_knob = new Sprite();
		_knob.buttonMode = true;
		_knob.useHandCursor = true;
		_knob.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
		_sprite.addChild(_knob);
		
		_label = new Label();
		_label.autoSize = true;
		_label.addTo(_sprite);
		
		_valueLabel = new Label();
		_valueLabel.autoSize = true;
		_valueLabel.addTo(_sprite);
	}
	
	function drawKnob(radius:Float):Void
	{
		var g = _sprite.graphics;
		g.clear();
		g.beginFill(0x000000);
		
		var g = _knob.graphics;
		g.clear();
		g.beginFill(Style.BACKGROUND);
		g.drawCircle(0, 0, radius);
		g.endFill();
		
		g.beginFill(Style.BUTTON_FACE);
		g.drawCircle(0, 0, radius - 2);
		g.endFill();
		
		g.beginFill(Style.BACKGROUND);
		var s = radius * .1;
		g.drawRect(radius - s * 4, -s, s * 4, 2 * s);
		g.endFill();
		
		_knob.x = _width / 2;
		_knob.y = _height / 2 + 20;
		updateValueView();
	}
	
	override function updateValueView():Void
	{
		_knob.rotation = -225 + (_value - _minValue) / (_maxValue - _minValue) * 270;
		formatValueLabel();
	}
	
	function formatValueLabel():Void
	{
		var mult:Int = Std.int(Math.pow(10, _precision));
		var val:String = Std.string(Math.round(_value * mult) / mult);
		var parts:Array<Dynamic> = val.split(".");
		if(parts[1] == null)
		{ 
			if(_precision > 0)
			{
				val += ".";
			}
			for(i in 0 ... _precision)
			{
				val += "0";
			}
		}
		else if(parts[1].length < _precision)
		{
			for(i in 0 ... _precision - parts[1].length)
			{
				val += "0";
			}
		}
		_valueLabel.text = val;
		_valueLabel.draw();
		_valueLabel.x = width / 2 - _valueLabel.width / 2;
	}
	
	// PUBLIC METHOD
	
	public override function draw():Void
	{
		super.draw();
		
		var radius = Math.min(_width, _height) / 2;
		drawKnob(radius);
		
		_label.text = _labelText;
		_label.draw();
		_label.x = _width / 2 - _label.width / 2;
		_label.y = 0;
		
		formatValueLabel();
		_valueLabel.y = _height + 20;
	}
	
	// HANDLERS
	
	var _startY:Float;
	
	var _startX:Float;
	
	var _eX:Float;
	
	var _eY:Float;
	
	var _diffCoefficient:Float;
	
	function onMouseDown(event:MouseEvent):Void
	{
		preinitMove();
		var stage = _sprite.stage;
		stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
	}
	
	function onMouseMove(event:MouseEvent):Void
	{
		var oldValue = _value;
		var diff = (_eX * (_sprite.mouseX - _startX) + _eY * (_sprite.mouseY - _startY)) * _diffCoefficient;
		_value += diff * (_maxValue - _minValue) * 270 / (380 * Math.PI);
		correctValue();
		if(_value != oldValue)
		{
			updateValueView();
			//dispatchEvent(new Event(Event.CHANGE));
		}
		preinitMove();
	}
	
	function preinitMove()
	{
		_startX = _sprite.mouseX;
		_startY = _sprite.mouseY;
		var rX = _knob.y - _sprite.mouseY;
		var rY = _sprite.mouseX - _knob.x;
		var mod = Math.sqrt(rX * rX + rY * rY);
		if (mod < 1)
		{
			_eX = 1;
			_eY = 0;
			mod = 1;
		}
		else
		{
			_eX = rX / mod;
			_eY = rY / mod;
		}
		_diffCoefficient = 1 / mod;
	}
	
	function onMouseUp(event:MouseEvent):Void
	{
		var stage = _sprite.stage;
		stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
		stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
	}
	
	// PROPERTIES
	
	public var labelPrecision(getLabelPrecision, setLabelPrecision):Int;
	var _precision:Int;
	function setLabelPrecision(decimals:Int):Int
	{
		_precision = decimals;
		return decimals;
	}
	function getLabelPrecision():Int
	{
		return _precision;
	}
	
	public var showValue(getShowValue, setShowValue):Bool;
	function setShowValue(value:Bool):Bool
	{
		_valueLabel.visible = value;
		return value;
	}
	function getShowValue():Bool
	{
		return _valueLabel.visible;
	}
	
	public var label(getLabel, setLabel):String;
	var _labelText:String;
	function setLabel(str:String):String
	{
		_labelText = str;
		draw();
		return str;
	}
	function getLabel():String
	{
		return _labelText;
	}
}